﻿using System;
using System.Linq;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using ConsolidationTool.Common;
using System.Collections.Generic;
using System.Data.Linq;
using Microsoft.SharePoint;
using System.Web.Script.Serialization;

namespace ConsolidationTool.WebParts.ControlTemplates.ConsolidationTool.WebParts
{
    public partial class PublishSelector : UserControl
    {
        public bool WithMonth { get; set; }
        public string Category { get; set; }
        public bool CheckControl = true;

        public string PublishKey
        {
            get
            {
                if (Category == "Budget")
                    return string.Format("{0}_Publish_{1}", Category, tbYear.Text);

                return string.Format("{0}_Publish_{1}_{2}", Category, tbYear.Text, tbMonth.Text);
            }
        }

        public class PublishItem
        {
            public string Title { get; set; }
            public string EntityName { get; set; }
            public string EntityCode { get; set; }
            public string Year { get; set; }
            public string Month { get; set; }
            public bool Locked { get; set; }
            public bool Published { get; set; }
        }
        public class PublishTable
        {
            public PublishTable(string category, string title, bool iscontorl)
            {
                this.Title = title;
                this.Category = category;
                this.isControl = iscontorl;
            }
            public string Title { get; set; }
            public string Url { get; set; }
            public string Category { get; set; }
            public bool isControl { get; set; }
        }

        protected void Page_Load(object sender, EventArgs e)
        {
            if (!string.IsNullOrEmpty(Request["c"]))
                CheckControl = bool.Parse(Request["c"]);

            monthRow.Visible = WithMonth;
            LoadAllTables();
            if (!IsPostBack)
                BindAllEntity(false);
        }

        public List<PublishItem> SelectedEntitys
        {
            get
            {
                List<PublishItem> temp = new List<PublishItem>();
                for (int i = 0; i < cbEntitys.Items.Count; i++)
                {
                    if (cbEntitys.Items[i].Selected)
                    {
                        temp.Add(new PublishItem()
                        {

                            EntityName = cbEntitys.Items[i].Value.Split('|')[0],
                            EntityCode = cbEntitys.Items[i].Value.Split('|')[1],
                            Year = tbYear.Text,
                            Month = tbMonth.Text

                        });
                    }
                }
                return temp;
            }
        }

        public void BindAllEntity(bool check)
        {
            if (!IsPostBack)
            {
                if (Category == "Budget")
                    tbYear.Text = BusinessService.GetConfiguration(Constants.Budget_Input_Year);
                else
                    tbYear.Text = BusinessService.GetConfiguration(Constants.Flash_Input_Year);
                tbMonth.Text = BusinessService.GetConfiguration(Constants.Flash_Input_Month);

            }
            cbEntitys.Items.Clear();
            var allEntity = BusinessService.getEntity();
            var publishedEntitys = GetProperty();

            allEntity.ForEach(p =>
            {
                if (!btLock.Visible)
                {
                    //hide lock and unlock button if current user not in admin group;;
                    var adminGroup = SPContext.Current.Web.SiteGroups["Reporting_Tool_Admin"];
                    btLock.Visible = btUnlock.Visible = adminGroup.ContainsCurrentUser;

                    //btLock.Visible = btUnlock.Visible = p.Region.ContainsCurrentUser;
                }

                if (p.Region.ContainsCurrentUser || p.SubRegionGroup.ContainsCurrentUser || p.ContainsCurrentUser)
                {
                    string entityName = string.Format("{0}-{1}-{2}", p.RegionName, p.subRegionName, p.entityName);
                    ListItem item = new ListItem(entityName, p.CoCd);
                    item.Value = string.Format("{0}|{1}", entityName, p.CoCd);

                    if (publishedEntitys != null)
                    {
                        PublishItem pitem = null;

                        if (Category == "Budget")
                            pitem = publishedEntitys.FirstOrDefault(a => a.EntityName == entityName && a.Year == tbYear.Text);
                        else
                            pitem = publishedEntitys.FirstOrDefault(a => a.EntityName == entityName && a.Year == tbYear.Text && a.Month == tbMonth.Text);

                        if (pitem != null)
                        {
                            item.Enabled = !pitem.Locked;
                       
                            string addtionOperation = pitem.Published ? " <b>Published!</b>" : "";
                            addtionOperation = pitem.Locked ? " <b>Locked!</b>" : addtionOperation;

                            item.Text += addtionOperation;
                        }
                    }

               //     item.Enabled = !check ? check : item.Enabled ;
                    cbEntitys.Items.Add(item);
                }
            });


        }


        #region Publish

        protected void btCheck_Click(object sender, EventArgs e)
        {
            ResetView();
            BindAllEntity(true);
        }

        protected void Publish_Click(object sender, EventArgs e)
        {
            if (!CheckControl)
            {
                Publish_OK_Click(sender, e);

                return;
            }

            var sEntity = new List<PublishTable>();

            AllTable.FindAll(p => p.Category == Category && p.isControl).ForEach(c =>
            {
                SelectedEntitys.ForEach(p =>
                {
                    if (!DoesCurrentSelectedLocked(p))
                    {
                        var item = PublishItemInstance(c, p);
                        if (item != null)
                            sEntity.Add(item);
                    }
                    else {
                        Page.ClientScript.RegisterStartupScript(this.GetType(), "fs-locked", "<script> alert('" + p.EntityName + "-" + p.Year + "-" + p.Month + " have been locked!');</script>");
                        return;
                    }
                });
            });

            PublishCheckArea.DataSource = sEntity;
            PublishCheckArea.DataBind();

            ResetView();
            PublishArea.Visible = true;

            Page.ClientScript.RegisterStartupScript(this.GetType(), "fs-ontrolStatusBeginCalc", "<script> ControlStatusBeginCalc();</script>");
        }

        private bool DoesCurrentSelectedLocked(PublishItem p)
        {
            var publishedEntitys = GetProperty();
            if (publishedEntitys == null) return false;
            PublishItem oldEntity = null;
            if (Category == "Budget")
                oldEntity = publishedEntitys.FirstOrDefault(a => a.EntityName == p.EntityName && a.Year == tbYear.Text);
            else
                oldEntity = publishedEntitys.FirstOrDefault(a => a.EntityName == p.EntityName && a.Year == tbYear.Text && a.Month == tbMonth.Text);

            return oldEntity == null ? false : oldEntity.Locked;
        }

        protected void Publish_OK_Click(object sender, EventArgs e)
        {
            if (SelectedEntitys.Count == 0)
                return;

            var publishedEntitys = GetProperty();

            //PublishItem sEntity = publishedEntitys.FirstOrDefault(a => a.EntityName == entityName && a.Year == tbYear.Text && a.Month == tbMonth.Text); 
            //if(sEntity==null)
            //    sEntity = new List<PublishItem>();

            var sEntity = new List<PublishItem>();

            SelectedEntitys.ForEach(p =>
            {
                var addItem = p;
                if (publishedEntitys != null)
                {

                    PublishItem oldEntity = null;
                    if (Category == "Budget")
                        oldEntity = publishedEntitys.FirstOrDefault(a => a.EntityName == p.EntityName && a.Year == tbYear.Text);
                        else
                        oldEntity =  publishedEntitys.FirstOrDefault(a => a.EntityName == p.EntityName && a.Year == tbYear.Text && a.Month == tbMonth.Text);

                    if (oldEntity != null)
                        addItem = oldEntity;

                    publishedEntitys.Remove(oldEntity);
                }
               var newitem= new PublishItem()
                {
                    EntityName = addItem.EntityName,
                    EntityCode = addItem.EntityCode,
                    Year = addItem.Year,
                    Month = addItem.Month,
                    Published = addItem.Published,
                    Locked = addItem.Locked
                };
               if (Category == "Budget")
                   newitem.Month = "0";


               sEntity.Add(newitem);

            });

            sEntity.ForEach(p =>
            {
                Publish(p);
            });

            if (publishedEntitys != null)
            {
                publishedEntitys.AddRange(sEntity);
            }
            else
                publishedEntitys = sEntity;

            SetProperty(publishedEntitys);

            lbActionStatus.Text += "Publish Done!";
            BindAllEntity(true);
        }

        private PublishTable PublishItemInstance(PublishTable c, PublishItem p)
        {
            string QueryTemplate = CreateQueryString(p);
            SPWeb web = SPContext.Current.Web;

            SPList list = web.Lists[c.Title];
            var field = list.Fields.TryGetFieldByStaticName("Status");

            var items = list.GetItems(new SPQuery()
            {
                Query = QueryTemplate
            });

            int itemCount = items.Count;
            if (itemCount > 0)
            {
                SPListItem item = items[0];
                return new PublishTable(c.Category, c.Title, c.isControl)
                {
                    Url = string.Format("{0}/{1}?List={2}&ID={3}&ContentTypeId={4}&isdlg=1&control=true", item.ParentList.ParentWebUrl, item.ContentType.DisplayFormUrl,
                    item.ParentList.ID,
                    item.ID, item.ContentTypeId)

                };

            }
            return c;
        }

        private void Publish(PublishItem p)
        {
            p.Published = true;
            ModifyStatus(p, FormStatus.Published, SPRoleType.WebDesigner);
        }


        #endregion

        #region Lock

        protected void Lock_Click(object sender, EventArgs e)
        {
            ResetView();
            var allPublishedEntity = GetProperty();

            if (allPublishedEntity == null)
                return;

            cbCanBeLock.Items.Clear();

            for (int i = 0; i < allPublishedEntity.Count; i++)
            {
                var p = allPublishedEntity[i];

                if (p.Published && !p.Locked)
                {
                    cbCanBeLock.Items.Add(new ListItem(p.EntityName, p.EntityCode));
                }
            }

            LockArea.Visible = true;
        }


        protected void Lock_OK_Click(object sender, EventArgs e)
        {
            var allPublishedEntity = GetProperty() as List<PublishItem>;

            for (int i = 0; i < allPublishedEntity.Count; i++)
            {
                var p = allPublishedEntity[i];
                var cbItem = cbCanBeLock.Items.FindByText(p.EntityName);
                if (cbItem == null) continue;
                if (cbItem.Selected)
                {
                    Lock(p);
                }
            }

            SetProperty(allPublishedEntity);
            lbActionStatus.Text = "Lock Done!";
            BindAllEntity(true);
        }

        private void Lock(PublishItem p)
        {
            p.Locked = true;
            ModifyStatus(p, FormStatus.Locked, SPRoleType.Reader);
        }

        #endregion

        #region Unlock


        protected void Unlock_Click(object sender, EventArgs e)
        {
            ResetView();
            var allLockedEntity = GetProperty() as List<PublishItem>;

            if (allLockedEntity == null)
                return;

            cbCanBeUnlock.Items.Clear();

            for (int i = 0; i < allLockedEntity.Count; i++)
            {
                var p = allLockedEntity[i];

                if (p.Locked)
                {
                    cbCanBeUnlock.Items.Add(new ListItem(p.EntityName, p.EntityCode));
                }
            }

            UnlockArea.Visible = true;
        }

        protected void Unlock_OK_Click(object sender, EventArgs e)
        {

            var allLockedEntity = GetProperty() as List<PublishItem>;

            for (int i = 0; i < allLockedEntity.Count; i++)
            {
                var p = allLockedEntity[i];

                var cbItem = cbCanBeUnlock.Items.FindByText(p.EntityName);
                if (cbItem == null) continue;

                if (cbItem.Selected)
                {
                    Unlock(p);
                }
            }

            SetProperty(allLockedEntity);
            lbActionStatus.Text = "Unlock Done!";
            BindAllEntity(true);
        }

        private void Unlock(PublishItem s)
        {
            s.Locked = false;
            s.Published = false;
            ModifyStatus(s, FormStatus.Draft, SPRoleType.WebDesigner);
            BindAllEntity(true);
        }


        #endregion


        #region Page Untity Function

        private SPListItem GetConfigItem(string pKey)
        {
            var configList = SPContext.Current.Web.Lists["Configuration"];
            var items = configList.GetItems(new SPQuery()
            {
                Query = string.Format(@"<Where>
                              <Eq>
                                 <FieldRef Name='Title' />
                                 <Value Type='Text'>{0}</Value>
                              </Eq>
                           </Where>", PublishKey)
            });
            if (items.Count > 0)
                return items[0];

            return null;
        }

        private void SetProperty(List<PublishItem> sEntity)
        {
            string valueTemp = (new JavaScriptSerializer()).Serialize(sEntity);
            var configList = SPContext.Current.Web.Lists["Configuration"];
            var newItem = GetConfigItem(PublishKey);
            if (newItem == null)
                newItem = configList.AddItem();

            newItem["Title"] = PublishKey;
            newItem["Value"] = valueTemp;
            newItem.Update();
        }

        private List<PublishItem> GetProperty()
        {
            var newItem = GetConfigItem(PublishKey);
            if (newItem == null)
                return null;

            string value = newItem["Value"] + "";

            return (new JavaScriptSerializer()).Deserialize<List<PublishItem>>(value);
        }

        private void ResetView()
        {
            PublishArea.Visible = false;
            LockArea.Visible = false;
            UnlockArea.Visible = false;
            lbActionStatus.Text = "";
        }

        private void ModifyStatus(PublishItem s, string status, SPRoleType roleType)
        {
            string QueryTemplate = CreateQueryString(s);

            Guid MywebGuid = SPContext.Current.Web.ID;
            Guid MysiteGuid = SPContext.Current.Site.ID;

            SPSecurity.RunWithElevatedPrivileges(delegate()
            {
                using (SPSite site = new SPSite(MysiteGuid))
                {
                    using (SPWeb web = site.OpenWeb(MywebGuid))
                    {
                        AllTable.FindAll(p => p.Category == Category).ForEach(p =>
                        {
                            SPList list = web.Lists[p.Title];
                            var field = list.Fields.TryGetFieldByStaticName("Status");

                            var items = list.GetItems(new SPQuery()
                            {
                                Query = QueryTemplate
                            });
                            try
                            {
                                int itemCount = items.Count;
                                for (int i = 0; i < itemCount; i++)
                                {
                                    SPListItem item = items[i];
                                    item["Status"] = status;
                                    item.Web.AllowUnsafeUpdates = true;
                                    item.Update();
                                    item.Web.AllowUnsafeUpdates = false;

                                    var entity = BusinessService.getEntity(s.EntityCode);
                                    Utilities.UserRoleAssignment(MysiteGuid, MywebGuid, list.ID, item.ID, entity, roleType);
                                }
                            }
                            catch (Exception ex)
                            {
                                lbActionStatus.Text += string.Format("<br/>List : {0} Status field does not exist!<br/>{1}<br/>", p.Title, ex.Message);
                            }
                        });
                    }
                }
            });
        }

        private string CreateQueryString(PublishItem s)
        {
            string QueryTemplate = string.Format(@" <Where>
                                                      <And>
                                                         <Eq>
                                                            <FieldRef Name='CoCd' />
                                                            <Value Type='Text'>{0}</Value>
                                                         </Eq>
                                                         <And>
                                                            <Eq>
                                                               <FieldRef Name='Year' />
                                                               <Value Type='Integer'>{1}</Value>
                                                            </Eq>
                                                            <Eq>
                                                               <FieldRef Name='Month' />
                                                               <Value Type='Integer'>{2}</Value>
                                                            </Eq>
                                                         </And>
                                                      </And>
                                                   </Where>", s.EntityCode, s.Year, s.Month);
            if (!WithMonth)
                QueryTemplate = string.Format(@"<Where>
                                          <And>
                                             <Eq>
                                                <FieldRef Name='CoCd' />
                                                <Value Type='Text'>{0}</Value>
                                             </Eq>
                                             <Eq>
                                                <FieldRef Name='Year' />
                                                <Value Type='Integer'>{1}</Value>
                                             </Eq>
                                          </And>
                                       </Where>", s.EntityCode, s.Year);
            return QueryTemplate;
        }

        List<PublishTable> AllTable = new List<PublishTable>();

        public void LoadAllTables()
        {
            AllTable.Add(new PublishTable("Actual", "Actual_NF1", false));
            AllTable.Add(new PublishTable("Actual", "Actual_NF2", false));
            AllTable.Add(new PublishTable("Actual", "ARAP INTERCO AGING", true));
            AllTable.Add(new PublishTable("Actual", "CAPEX", true));
            AllTable.Add(new PublishTable("Actual", "Balance Sheet", true));
            AllTable.Add(new PublishTable("Actual", "Direct Cash flow", true));
            AllTable.Add(new PublishTable("Actual", "External Services", true));
            AllTable.Add(new PublishTable("Actual", "FC_SG_A", false));
            AllTable.Add(new PublishTable("Actual", "Indirect Cash flow", true));
            AllTable.Add(new PublishTable("Actual", "Inventory", true));
            AllTable.Add(new PublishTable("Actual", "P_L", false));
            AllTable.Add(new PublishTable("Actual", "Gross Fixed Cost", true));
            AllTable.Add(new PublishTable("Actual", "SBEW", false));
            AllTable.Add(new PublishTable("Actual", "Depreciation", false));
            AllTable.Add(new PublishTable("Actual", "Actual_ARAP", true));
            AllTable.Add(new PublishTable("Actual", "Actual_VM", false));
            AllTable.Add(new PublishTable("Actual", "Actual_VM_YTD", false));

            AllTable.Add(new PublishTable("Flash", "HR", true));
            AllTable.Add(new PublishTable("Flash", "Product Sales By RGC", false));
            AllTable.Add(new PublishTable("Flash", "Purchase Interco Declaration", false));
            AllTable.Add(new PublishTable("Flash", "Sales Interco Declaration", true));
            AllTable.Add(new PublishTable("Flash", "Quality&Safety", true));
            AllTable.Add(new PublishTable("Flash", "Trade Sales By RGC", false));
            AllTable.Add(new PublishTable("Flash", "Sales&Commission&Service", false));
            AllTable.Add(new PublishTable("Flash", "Actual_Flash_VM", false));

            AllTable.Add(new PublishTable("Budget", "Budget_BS", true));
            AllTable.Add(new PublishTable("Budget", "Budget_CAPEX", true));
            AllTable.Add(new PublishTable("Budget", "Budget_DCF", true));
            AllTable.Add(new PublishTable("Budget", "Budget_Depreciation", false));
            AllTable.Add(new PublishTable("Budget", "Budget_ES", true));
            AllTable.Add(new PublishTable("Budget", "Budget_FSA", false));
            AllTable.Add(new PublishTable("Budget", "Budget_GRFC", true));
            AllTable.Add(new PublishTable("Budget", "Budget_HR", true));
            AllTable.Add(new PublishTable("Budget", "Budget_ICF", true));
            AllTable.Add(new PublishTable("Budget", "Budget_Inventory", true));
            AllTable.Add(new PublishTable("Budget", "Budget_NF2", false));
            AllTable.Add(new PublishTable("Budget", "Budget_NF1", false));
            AllTable.Add(new PublishTable("Budget", "Budget_PI", false));
            AllTable.Add(new PublishTable("Budget", "Budget_PL", false));
            AllTable.Add(new PublishTable("Budget", "Budget_PSBR", false));
            AllTable.Add(new PublishTable("Budget", "Budget_QS", false));
            AllTable.Add(new PublishTable("Budget", "Budget_SBEW", false));
            AllTable.Add(new PublishTable("Budget", "Budget_SCS", false));
            AllTable.Add(new PublishTable("Budget", "Budget_SID", true));
            AllTable.Add(new PublishTable("Budget", "Budget_TSBR", false));

            AllTable.Add(new PublishTable("Forecast", "Forecast_HR", true));
            AllTable.Add(new PublishTable("Forecast", "Forecast_CAPEX", false));
            AllTable.Add(new PublishTable("Forecast", "Forecast_DCF", false));
            AllTable.Add(new PublishTable("Forecast", "Forecast_PL", false));
            AllTable.Add(new PublishTable("Forecast", "Forecast_PSBR", false));
            AllTable.Add(new PublishTable("Forecast", "Forecast_TSBR", false));
            AllTable.Add(new PublishTable("Forecast", "Forecast_SCS", false));
            AllTable.Add(new PublishTable("Forecast", "Forecast_SID", true));


        }

        #endregion


    }
}
